Method for compression of object code interpreted by tree-structured expression factorization

ABSTRACT

The invention concerns a method characterized in that it comprises identifying (block  2 ), in the interpreted object-coded programme, similar non-contiguous groups of instructions, of arbitrarily complex structure, replacing (block  5 ) all or part of said groups in the interpreted object code of the programme with newly-created specialized instructions and instrumenting the interpreter and/or the interpreted object code of the programme so as to render it capable of implementing the newly-created instructions. The invention is applicable to compression of an interpreted object code in a system comprising an interpreter.

BACKGROUND OF THE INVENTION

[0001] 1. Field of the Invention

[0002] This present invention concerns a method for the compression of interpreted object code by the factorisation of arborescent expressions.

[0003] 2. Description of the Prior Art

[0004] In general, it is known that embedded systems which have data processing resources, such as smartcards (with microprocessor) or analogue cards for example, are designed so as to execute object codes obtained by the compilation of a source program, usually written in a high-level language. As a consequence, these systems comprise an interpreter which performs software interpretation of the instructions of the object code into machine-code instructions which are directly executable by the microprocessor. This interpreter can be installed, for example, in a memory associated with the microprocessor, in general a read-only memory (ROM) or a programmable memory.

[0005] It so happens that many applications use embedded systems which are as small as possible, and this involves limiting the size of memories and therefore of the application programs used.

[0006] With the aim of partially surmounting this problem, a proposal has been put forward for compacting the source code.

[0007] However, this solution has the disadvantages that it cannot be used in the event that one does not have the source code (which is the case most of the time) and the requirement to instrument the generator of interpreted object code, which is a highly complex tool.

[0008] Furthermore, a proposal has also been made to perform compacting of the interpreted object code by searching in the object code for successive identical standard instruction sequences, and counting the occurrences of these identical sequences. A test to decide whether this number of occurrences is greater than a reference number is then used to decide whether or not to create a specific code instruction with which the sequence is associated. A replacement for each occurrence of the sequence by the specific instruction code is effected in the interpreted object code in order to generate a compacted object code with which an execution file is associated.

[0009] In fact, this compression method performs a factorisation of instruction groups in the program in interpreted object code.

OBJECT OF THE INVENTION

[0010] More particularly, the invention has the objective of improving the compacting of the program in interpreted object code, no longer by factorising the contiguous instruction groups but rather by identifying and processing the non-contiguous instruction groups so as to obtain new executable instructions by the use of original instrumentation systems of the interpreter.

[0011] This applies particularly, though not exclusively, to those interpreters which have a stack to carry out all the calculations.

SUMMARY OF THE INVENTION

[0012] To this end, it proposes a compression method which comprises a first step consisting of making said interpreter configurable in relation to the definition of new instructions, and then, for each program or program set, an object code interprets the following steps:

[0013] the identification in this program or this program set of similar but not necessarily contiguous instruction groups, with or without their static arguments (a static argument is an instruction with an argument located in the very code of the program, in contrast to a dynamic argument which is located in a register, a variable or an operand stack).

[0014] the replacement of all or part of these groups in the interpreted object code of the program or programs concerned by the newly-created specialised instructions,

[0015] the configuration of the interpreter in relation to said newly-created specialised instructions so as to render it capable of interpreting the program or programs containing the newly-created instructions.

[0016] Advantageously, this method can comprise a test step with a view to choosing the instruction groups to be replaced so that, after replacement, one gets a compressed program of a size which is smaller than that of the program before compression, this choice taking account of the overcost related to instrumentation of the execution environment and/or of the object code.

BRIEF DESCRIPTION OF THE DRAWINGS

[0017] The embodiments of the invention will be described hereafter, in terms of non-exhaustive examples, with reference to the annexed drawings in which:

[0018]FIG. 1 is a flow diagram illustrating the operation of the method according to the invention;

[0019]FIG. 2 is a schematic representation showing the modifications to the operand stack during the execution of an example of a JavaCard bytecode sequence;

[0020]FIG. 3 is a schematic representation showing the changes to the operand stack and to the internal stack during execution of the instruction sequence illustrated in FIG. 2 after compression, which has introduced the ssub_sadd_baload specialised instructions.

[0021]FIG. 4, in an analogue manner, illustrates the execution of this same instruction sequence using a single stack.

DESCRIPTION OF THE PREFERRED EMBODIMENTS

[0022] In accordance with the flow diagram represented in FIG. 1, implementation of the method described above can comprise an operational sequence which has the following steps:

[0023] the construction of a representation of the calculations performed by the program in the form of arborescent expressions (block 1),

[0024] identification, in these arborescent expressions, of sequences of sub-expressions corresponding to the motifs appearing most frequently (in accordance with a criterion which has been left open, such as a threshold function concerning the frequencies of occurrence), where these motifs can be complete trees or configured by arguments (block 2), that is with or without static argument,

[0025] the selection of a sequence of tree motifs (M₁, . . . , M_(n)) (block 3),

[0026] the association with the sequence of sub-expressions, selected in the preceding step, of a new instruction of the interpreter (block 4),

[0027] the reconstruction of an interpreted object form from the representation in the form of arborescent expressions, by replacing, in the interpreted object code of the program, the not necessarily contiguous instruction groups corresponding to each occurrence of the sequence of sub-expressions selected by the associated instruction (block 5),

[0028] addition of the definitions of the newly-created instructions to the file of the interpreter object code of the program and/or to the interpreter (given that the selection step (block 3) is based on state-of-the-art techniques).

[0029] Of course this operational sequence then comprises a test (block 6) to ascertain whether or not the instruction set is exhausted, or if compression has become impossible. In the negative case, the system returns to block 1 to carry out a new sequence of compression operations. In the affirmative case, however, the sequence ends (block 7).

[0030] The invention proposes a technique for identification of the non-contiguous instruction groups which is based on the construction of a representation of the interpreted object code program in the form of arborescent expressions.

[0031] To this end, it offers to find, in the object code, complex calculation expressions (as they can appear, for example, in the high-level language which was used to write the program before compilation), and to identify, from among these expressions, sequences of sub-expressions which appear frequently in the program.

[0032] More precisely, the invention aims to represent the calculation operation groups in the form of arborescent expressions, given that in each case:

[0033] it implements an interpreter which has a stack to perform its calculations,

[0034] a calculation operation is an instruction which takes arguments from an operand stack and returns (or does not return) a result to this stack,

[0035] a calculation expression tree can be a group of instructions which are separated from each other by arbitrarily large distances in the original object code,

[0036] by definition, for each calculation operation, op, of the intermediate object language, the associated tree constructor will be denoted op, and the arity of the op constructor is given by the number of arguments that the op operation reads from the stack of the interpreter.

[0037] In this example, the method according to the invention uses a simple iterative calculation algorithm which constructs a representation in the form of arborescent expressions for each sub-program of the interpreted object code from its instruction sequence by successive rewrites. Each rewrite step is defined in an extended instruction sequence, S, as follows, given that an extended expression is either a standard instruction or an arborescent expression:

[0038] If S=(J₁, . . . , J_(m),E₁, . . . , E_(n), op, J_(m+1), . . . J_(k)) where op is of arity n

[0039] then we rewrite S as:

[0040] S′=(J₁, . . . , J_(m), op(E₁, . . . , E_(n)), J_(m+1), . . . J_(k))

[0041] Otherwise S remains unchanged

[0042] If (I₁, . . . , I_(n)) is the instruction sequence of the P sub-program, then this algorithm is applied iteratively to the extended instruction sequence (I′₁, . . . , I′_(n)) where:

[0043] I′=c if I_(i)=c where c is of arity 0.

[0044] I′_(i)=I_(i) otherwise.

[0045] up to the point where any other rewrite has become impossible.

[0046] The extended instruction sequence obtained at the end of this calculation is the representation of sub-program P in the form of arborescent expressions P.

[0047] The invention will be illustrated below with reference to the following examples which are given as a guide only, in which:

[0048] Example 1 illustrates a method of representation, in the form of arborescent expressions, of a bytecode sequence expressed in JavaCard code.

[0049] Example 2 shows a method of factorisation of this sequence from its representation in arborescent form.

[0050] Example 3 is a method for the definition of specialised instructions as introduced in Example 2, using an internal stack.

[0051] Example 4 is a method for the definition of specialised instructions as introduced in Example 2, using a single stack.

EXAMPLE 1

[0052] In this example, just like all the others, we are considering the JavaCard software architecture. JavaCard is a complete software architecture (comprising an object-oriented high-level language, an interpreted object code, an object code interpreter of the stack machine type, an execution environment, standard libraries and a system of secure interactions between programs accommodated on a single card) for the execution of programs on smartcards in a multiple-application context. A JavaCard program is known as an applet. It is a passive reactive program which interacts with the terminal to which the card is connected, in the form of message transmission of the command-response type, the command being emitted by the terminal only, with the applet sending back a response for each command received. The interpreted object code language considered here is JavaCard bytecode. The bytecode interpreter is the JavaCard virtual machine (JCVM) which is installed in the smartcards.

[0053] Let us consider a JavaCard program which contains the following bytecode sequence:

[0054] sload 1

[0055] sload 2

[0056] sadd

[0057] sload 3

[0058] ssub

[0059] sload 4

[0060] sconst 2

[0061] baload

[0062] sconst 1

[0063] sconst 2

[0064] invokestatic “someComputation (short, byte, short, short)”

[0065] The sload n instruction reads the content of variable n and stores it at the top of the stack, the sadd instruction does the addition (and the ssub instruction the subtraction) of the two integers located at the top of the stack, storing the result in the stack, the sconst c instruction stacks the integer constant c, the baload instruction reads an element from the bytes table storing its content at the top of the stack, and the invokestatic instruction calls a sub-program. The integers concerned here are shorts, which are 16-bit integers, or bytes, which are 8-bit integers.

[0066] The changes to the operand stack during the execution of this instruction sequence are shown in FIG. 2.

[0067] The representation of the previous sequence in the form of arborescent expressions has the following form:

[0068] invokestatic “someComputation (short, short, short, byte)” (ssub (sadd (sload 1, sload 2), sload 3), baload (sload 4, sconst 2), sconst 1, sconst 2)

[0069] We obtain a complex calculation expression similar to that which could be written, for example, in the high-level programming language which was used to produce the object code of the program concerned (JavaCard in this case).

[0070] The factorisation of arborescent expressions in accordance with the method according to the invention comprises a first step which consists of identifying the sequences of recurring motifs in the arborescent expressions appearing in the intermediate form of the program. A motif, M, is a term, that is an incomplete tree, of which the missing parts are represented by variables called x₁, X₂, . . . , X_(n). We will note the indices of the variables in ascending order of their occurrence in the postfixed path (that is in depth, from left to right, exploring the threads of a node before the node itself) of the tree to which they belong. For a sequence of motifs (M₁, . . . , M_(k)) the variables appearing in motifs M₁, . . . , M_(k) are also numbered in ascending order of their appearance in the sequence of motifs, moving through them from left to right, such as the following sequence for example: (M₁ (x₁, x₂), M₂(x₃, x₄, x₅), M₃(x₆)). If we associate a specialised instruction I_((M1, . . . , Mk)) with each sequence of motifs (M₁, . . . , M_(k)) selected for factorisation, then the factorisation operation F(E) of an arborescent expressions E into a sequence of instructions is defined in the following manner (in accordance with the order of the cases):

[0071] F(c(E₁, . . . , E_(j), M₁(E¹ ₁, . . . , E¹ _(n1)), . . . , M_(k)(E^(k) ₁, . . . , E^(k) _(nk)), E_(j+1), . . . , E_(m))=F(E₁) o . . . o F(E_(j)) o F(E¹ ₁) o . . . o F(E¹ _(n1)) o . . . o F(E^(k) ₁) o . . . o F(E^(k) _(nk)) o (I_((M1, . . . , Mk)) o F(E_(j+1)) o . . . o F(E_(m)) o (c) if the sequence (M₁, . . . , M_(k)) is selected for factorisation.

[0072] F(c)=(c), if c is of arity 0.

[0073] F(c(E₁, . . . , E_(n))=F(E₁) o . . . . o F(E_(n)) o (c), if c is of arity n.

[0074] In these expressions, as in the remainder of the description, operator 0 denotes concatenation of the instruction sequence.

[0075] The search for sequences of motifs can be accomplished by numbering of the terms of limited size and filtering of the arborescent expressions of the program in accordance with these terms. The execution of this search, as well as the function for the choice of terms to factorise, are left open, because these involve the conventional techniques of the state of the art. If P=(J₁, J₂, . . . , J_(m)) is the intermediate representation of sub-program P in the form of extended instruction sequences, which are either standard instructions or arborescent expressions, then the factorisation of P is defined by the following standard instruction sequence:

[0076] Fact (J₁) o Fact (J₂) o . . . o Fact (J_(m))

[0077] where Fact (J)=J if J is a standard instruction

[0078] and F (J) if J is an arborescent expression.

[0079] Example 2 below illustrates a method for the factorisation of expression trees of the bytecode sequence of example 1.

EXAMPLE 2

[0080] It is assumed that, in the program containing the code of Example 1, the motif search algorithm is selected as candidate for factorisation of the following motif sequence:

[0081] (ssub (sadd (x₁, x₂), x₃), baload (x₄, x₅))

[0082] We name as ssub_sadd_baload the specialised instruction associated with this motif sequence. Then, after factorisation of the corresponding bytecode sequence, we obtain the following bytecode sequence:

[0083] sload 1

[0084] sload 2

[0085] sload 3

[0086] sload 4

[0087] sconst 2

[0088] ssub_sadd_baload

[0089] sconst 1

[0090] sconst 2

[0091] invokestatic “someComputation (short, byte, short, short)”

[0092] As mentioned previously, the method according to the invention comprises a step for instrumentation of the interpreter and/or of the interpreted object code file of the program so as to make it suitable for implementation of the newly created instructions in the executable.

[0093] This step occurs in the case where each specialised instruction is defined within the interpreter and/or in the object code of the program, by a sequence of instructions of the interpreted object language. The case of native implementation of these operations is not covered.

[0094] The execution of a specialised instruction requires modification of the method of execution of the interpreter, since factorisation breaks the logical link between the various intermediate calculations. Thus, in example 2, during execution of the specialised instruction, the addition operation must fetch its arguments from deep within the stack. The result of the addition cannot simply be stored at the top of the stack, since it corresponds to the first argument of the subtraction, which must necessarily be at a level below that of its second argument in the stack. There are two possible ways of instrumenting the interpreter to execute these instructions, namely a first way consisting of using an internal stack, and a second way consisting of performing a shift in the operand stack.

[0095] The first solution consists of using an internal operand stack during the execution of a specialised instruction, in order to perform all of the operations of which it is composed. The arguments used are copied from the standard operand stack to the internal stack by means of a new instruction, get_arg n, which takes as argument level n of the standard operand stack (from the top of the stack which corresponds to level 0) to be copied to the internal stack. In addition, it is necessary to associate the number of its arguments with each specialised instruction, in order to be able to remove them from the standard stack at the end of execution of the instruction, and to copy the residual content of the internal stack to the standard operand stack (which constitutes the final result of the associated instruction sequence).

[0096] If (M₁, . . . , M_(k)) is a sequence of motifs whose variables are x₁, . . . , x_(n), (that is all of the variables appearing in all the motifs of the sequence, numbered in accordance with the trajectory from left to right of the sequence and in accordance with the postfixed trajectory of each motif), then the semantic S(I_((M1, . . . , Mk))) of the associated specialised instruction I_((M1, . . . , Mk)), is the standard instruction sequence defined recursively in the following manner:

[0097] S(x_(i))=(get_arg (n-i))

[0098] S(c)=(c), if c is of arity 0

[0099] S(c(E₁, . . . , E_(k)))=S(E₁) o . . . o S(E_(k)) o (c), if c is of arity k.

[0100] Example 3 illustrates a method for using an internal operand stack in the case of the specialised instruction ssub-ssad_baload of Example 2.

EXAMPLE 3

[0101] The code corresponding to the definition of the specialised instruction ssub_sadd_baload of Example 2 is then as follows:

[0102] get_arg 4

[0103] get_arg 3

[0104] sadd

[0105] get_arg 2

[0106] ssub

[0107] get_arg 1

[0108] get_arg 0

[0109] baload

[0110] The changes to the operand stack and to the internal stack during execution of the factorised instruction sequence of Example 2 are shown in FIG. 3.

[0111] The second solution for instrumentation of the interpreter uses only a single stack, the standard operand stack, but also introduces jump operations in the stack which allows one to position oneself at any arbitrary level. When an operation is performed within the stack, all of the levels located above are shifted (upwards or downwards according to whether the instruction of the executed interpreted language consumes arguments and/or stacks a result).

[0112] A new instruction, down n, has to be used to allow one to move by n levels below the current stack level, and also an up instruction which allows one to move by one level above the current stack level. No other information is necessary for execution of the specialised instruction. At the end of execution of the specialised instruction, the stack contains the final result of the associated instruction group.

[0113] If (M₁, . . . , M_(k)) is a sequence of motifs whose variables are x₁, . . . , x_(n), then we define an auxiliary semantic S′(I_((M1, . . . , Mk))) of the specialised instruction I_((M1, . . . , Mk)). This auxiliary semantic consists of the standard instruction sequence defined recursively as follows:

[0114] S′(x_(i))=(up)

[0115] S′(c)=(c), if c is of arity 0

[0116] S′(c(E₁, . . . , E_(k)))=S′(E₁) o . . . o S′(E_(k)) o (c), if c is of arity k.

[0117] The semantic S(I_((M1, . . . , Mk))) of the specialised instruction is the following instruction sequence:

[0118] S (I_((M1, . . . , Mk)))=(down n) o S′(I_((M1, . . . , Mk)))

[0119] The initial down n instruction is used to move to a level below the first argument of the specialised instruction, which is the argument located at the lowest level in the stack. Since the numbering order of the arguments is equal to their order of evaluation by the specialised instruction, each read of an argument requires a single shift upwards of the stack pointer using the up instruction.

[0120] Example 4 illustrates an instrumentation method which uses only the standard operand stack in the case of specialised instruction ssub_ssad_baload of Examples 1 and 2.

EXAMPLE 4

[0121] The code corresponding to the definition of specialised instruction ssub_ssad_baload is then as follows:

[0122] down 5

[0123] up

[0124] up

[0125] sadd

[0126] up

[0127] ssub

[0128] up

[0129] up

[0130] baload

[0131] The changes to the operand stack during the execution of this instruction sequence are shown in FIG. 4. At each execution step, we have shown, by a pointer in the form of an arrow, the level in the stack where the calculations are performed.

[0132] It should be noted that the instruction sequence

[0133] down 5

[0134] up

[0135] up

[0136] is equivalent to the single instruction

[0137] down 3

[0138] This optimisation enables the space necessary for instrumentation of the interpreter to be reduced. 

1. A method for the compression of interpreted object code in a system with an interpreter which can be used to perform software interpretation of the instructions of the object code into instructions in machine language, which are directly executable by a processor, said method comprising a first step consisting of making said interpreter configurable in relation to the definition of new instructions, and then, for each program or program set, an object code interprets the following steps: the identification in this program or this programm set of similar but not necessarily contiguous instruction groups, with or without their static arguments, the replacement of all or part of these groups in the interpreted object code of the program or programs concerned by the newly-created specialised instructions, the configuration of the interpreter in relation to said newly-created specialised instructions so as to render it capable of interpreting the program or programs containing the newly-created instructions.
 2. A method according to claim 1, comprising a test step with a view to choosing the instruction groups to be replaced so that, after replacement, one gets a compressed program of a size which is smaller than that of the program before compression, this choice taking account of the overcost related to instrumentation of the execution environment and/or of the object code.
 3. A method according to claim 1, comprising an operating sequence which has the following steps: the construction of a representation of the calculations performed by the program in the form of arborescent expressions (block 1), identification, in these arborescent expressions, of sub-expressions corresponding to recurring sequences, where these motifs can be complete trees or configured by arguments (block 2), that is with or without static argument, the association of a new instruction of the interpreter (block 4) with each of these sequences of motifs, the reconstruction of an interpreted object form from the representation in the form of arborescent expressions, by replacing the code corresponding to the constituted motif sequences with not-necessarily-contiguous instruction groups identified by the associated instruction. the addition of definitions of the newly-created instructions to the file of the interpreter object code of the program and/or to the interpreter.
 4. A method according to claim 3, wherein said identification is performed according to a criterion consisting of a threshold function relating to the frequency of occurrence of said motif sequences.
 5. A method according to claim 3, characterised in that it uses an iterative calculation algorithm which constructs a representation in the form of arborescent expressions for each sub-program of the interpreted object code from its instruction sequence by successive rewrites.
 6. A method according to claim 3, comprising a search for motifs by numbering of the terms and filtering of the arborescent expressions of the program according to these terms.
 7. A method according to claim 3, comprising, in the event that it implements an interpreter of the stack machine type, a modification of a method of execution of the interpreter during the execution of a specialised instruction, where the instrumentation of the interpreter to execute these instructions comprises either an internal stack or the execution of a shift of the operand stack.
 8. A method according to claim 7, wherein, in the event of using an internal operand stack, the arguments used are copied from the standard operand stack to the internal stack by means of a new instruction, get_arg n, which takes as argument level n of the standard operand stack to be copied to the internal stack, and where it is necessary to associate the number of its arguments with each specialised instruction, in order to be able to remove them from the standard stack at the end of execution of the instruction, and to copy the residual content of the internal stack to the standard operand stack.
 9. A method according to claim 7, comprising, in the event that one performs a shift in the operand stack, a new instruction, down n, used to move n levels below the current stack level, and also an up instruction which allows one to move one level above the current stack level. 